
/*******************************************************************************************
file name: fan_ctrl.c
data: 2022.4.19
description:   
*******************************************************************************************/
#include "main.h"
#include <string.h>
#include "IDriver.h"
#include "fan_ctrl.h"
#include "Control.h"
#include "ModbusRegister.h"

#define IO_DC_FAN_FEEDBACK1     HAL_GPIO_ReadPin(DCFAN_SPEED1_GPIO_Port, DCFAN_SPEED1_Pin)  //si11(gpio_input_bit_get (GPIOA, GPIO_PIN_7)) 
#define IO_DC_FAN_FEEDBACK2     HAL_GPIO_ReadPin(DCFAN_SPEED2_GPIO_Port, DCFAN_SPEED2_Pin)  //(gpio_input_bit_get (GPIOB, GPIO_PIN_1)) 

dcfanParam g_DCfan1Param,g_DCfan2Param;



u8 Hal_GetFanInput(u8 index)//����1��0������������
{
	u8 State = 0;
	u8 Tempindex;
  Tempindex = index;
	
	switch(Tempindex)
	{
		case 0:
				if(IO_DC_FAN_FEEDBACK1 == 0)
				{
					State = 1;
				}	
		
	
		break;
				
		case 1:
				if(IO_DC_FAN_FEEDBACK2 == 0)
				{
					State = 1;
				}	
	 
	
		break;
		
			
		default:
			break;
	}
	
	return State;
}



void Set_AimSpeed(u8 i,u16 value)
{
	if((value > 1000)||(i > 1))
	{
		return;
	
	}
	if(i == 0)
	{
			g_DCfan1Param.AimSpeed = value;
	}
	else if(i == 1)
	{
			g_DCfan2Param.AimSpeed = value;
	}

}

u16 Get_feedBackSpeed(u8 i)
{
	if(i > 1)
	{
		return 0;
	
	}
	if(i == 0)
	{
			return g_DCfan1Param.feedBackSpeed;
	}
	else
	{
			return g_DCfan2Param.feedBackSpeed;
	}


}
   

/*******************************************************************************************
function name:  DcFAN_duty_calculate
description:    calculate duty
*******************************************************************************************/
static uint16_t dcfan_duty_calculate(dcfanParam *Param)
{
    uint16_t adjustValue,deviation,UpDown;
    float duty;
   
    if(Param->AimSpeed > Param->feedBackSpeed)
    {
        deviation = Param->AimSpeed - Param->feedBackSpeed;
        UpDown = 1;
    }
    else
    {
        deviation = Param->feedBackSpeed - Param->AimSpeed;
        UpDown = 0;
    }  
    
    if(deviation > DCFAN_DEVIATION1)
    {
       duty = DCFAN_DUTY_ADJUST1;
    }
    else if(deviation > DCFAN_DEVIATION2)
    {
       duty = DCFAN_DUTY_ADJUST2;
    }
    else if(deviation > DCFAN_DEVIATION3)
    {
       duty = DCFAN_DUTY_ADJUST3;
    }
    else if(deviation > DCFAN_DEVIATION4)
    {
       duty = DCFAN_DUTY_ADJUST4;
    }
    else if(deviation > DCFAN_DEVIATION5)
    {
       duty = DCFAN_DUTY_ADJUST5;
    }else
    {
       duty = 0;
    }
    if(Param->AimSpeed <= 400)
    {
       duty = 0.5*duty;
    }  
    
    adjustValue = (uint16_t)(duty * DCFAN_PERIOD);
    if(adjustValue != 0)
    {
        if(UpDown == 1)
        {
            Param->duty += adjustValue;
            if(Param->duty > DCFAN_MAXDUTY)
            {
                Param->duty = DCFAN_MAXDUTY;
            } 
        }
        else
        {
            if(Param->duty > adjustValue)
            {
                Param->duty -= adjustValue;
                if(Param->duty < DCFAN_MINDUTY)
                {
                    Param->duty = DCFAN_MINDUTY;
                } 
            }
            else
            {
                Param->duty = DCFAN_MINDUTY;
            }               
        } 
        return 1;
    }     
    return 0;
}


/*******************************************************************************************
function name:  DcFan1Ctrl
description:    control DCFAN1
*******************************************************************************************/
void DcFan1_Ctrl(void)
{
    float temp_cal,temp_fg;
    
    if((g_DCfan1Param.AimSpeed > 0) && (g_DCfan1Param.ErrorFlag == 0))//run
    {
       // timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM1);
       // timer_channel_output_state_config(TIMER2, TIMER_CH_0,TIMER_CCX_ENABLE);
        
        if(g_DCfan1Param.CtlTimeSpan > DCFAN_UPDATE_TIME)       //1000ms update
        {
            g_DCfan1Param.CtlTimeSpan = 0;
            temp_fg = (float)DCFAN_FG;
            temp_cal =(float)((g_DCfan1Param.PulseCntCur / temp_fg) * 60 * CORR_FACTOR);
            g_DCfan1Param.feedBackSpeed = (uint16_t)(temp_cal);
            
            g_DCfan1Param.PulseCntLast = g_DCfan1Param.PulseCntCur;
            g_DCfan1Param.PulseCntCur = 0;
            
            if(g_DCfan1Param.feedBackSpeed < DCFAN_MINSPEED)   //minimum speed
            {
                g_DCfan1Param.ErrorCnt ++;
                if(g_DCfan1Param.ErrorCnt > DCFAN_MAXERROR)    //10s
                {
                    g_DCfan1Param.ErrorCnt = 0;
                    g_DCfan1Param.ErrorFlag = 1;
                } 
            }
            else
            {
                g_DCfan1Param.ErrorCnt = 0;
                g_DCfan1Param.ErrorFlag = 0;
            }
            
            if(g_DCfan1Param.feedBackSpeed != g_DCfan1Param.AimSpeed)
            {
                if(dcfan_duty_calculate(&g_DCfan1Param) == 1)
                {
									ISet_PWM_Value	(	0	,		g_DCfan1Param.duty	);
                   // timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, g_DCfan1Param.duty);
                }
            }
        }
    }
    else    //stop
    {
      //  timer_channel_output_state_config(TIMER2, TIMER_CH_0,TIMER_CCX_DISABLE);   
        memset(&g_DCfan1Param,0,sizeof(g_DCfan1Param));
        g_DCfan1Param.duty = DCFAN_INITDUTY;
			  ISet_PWM_Value	(	0	,		0	);
       // timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, g_DCfan1Param.duty);
    }
		InputReg[REG_FAN1_DUTYCYCLE] = g_DCfan1Param.duty;
}

/*******************************************************************************************
function name:  DcFan1Ctr2
description:    control DCFAN2
*******************************************************************************************/
void DcFan2_Ctrl(void)
{
    float temp_cal,temp_fg;
    
    if((g_DCfan2Param.AimSpeed > 0) && (g_DCfan2Param.ErrorFlag == 0)) //run
    {    
       // timer_channel_output_mode_config(TIMER2, TIMER_CH_2, TIMER_OC_MODE_PWM1);
        //timer_channel_output_state_config(TIMER2, TIMER_CH_2,TIMER_CCX_ENABLE);
        
        if(g_DCfan2Param.CtlTimeSpan > DCFAN_UPDATE_TIME)   //1s update
        {
            g_DCfan2Param.CtlTimeSpan = 0;
            temp_fg = (float)DCFAN_FG;
            temp_cal =(float)((g_DCfan2Param.PulseCntCur / temp_fg) * 60 * CORR_FACTOR);
            g_DCfan2Param.feedBackSpeed = (uint16_t)(temp_cal);
            
            g_DCfan2Param.PulseCntLast = g_DCfan2Param.PulseCntCur;
            g_DCfan2Param.PulseCntCur = 0;
            
            if(g_DCfan2Param.feedBackSpeed < DCFAN_MINSPEED)   //minimum speed
            {
                g_DCfan2Param.ErrorCnt ++;
                if(g_DCfan2Param.ErrorCnt > DCFAN_MAXERROR)
                {
                    g_DCfan2Param.ErrorCnt = 0;
                    g_DCfan2Param.ErrorFlag = 1;
                }
            }
            else
            {
                g_DCfan2Param.ErrorCnt = 0;
                g_DCfan2Param.ErrorFlag = 0;  
            }
               
            if(g_DCfan2Param.feedBackSpeed != g_DCfan2Param.AimSpeed)
            {
                if(dcfan_duty_calculate(&g_DCfan2Param) == 1)
                {
                   // timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, g_DCfan2Param.duty);
									 ISet_PWM_Value	(	1	,		g_DCfan2Param.duty	);
                }
            }
        }
    }
    else    //stop
    {
       // timer_channel_output_state_config(TIMER2, TIMER_CH_2,TIMER_CCX_DISABLE);  
        memset(&g_DCfan2Param,0,sizeof(g_DCfan2Param));
        g_DCfan2Param.duty = DCFAN_INITDUTY;
			  ISet_PWM_Value	(	1	,		0	);
       // timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, g_DCfan2Param.duty);
    }
}

/*******************************************************************************************
function name:  internalDcFanFeedBack
description:    feedback Dcfan1 Dcfan2 
*****************************************************************************u*************/
void DcFan_FeedBack(void)
{
    if(g_DCfan1Param.AimSpeed > 0)
    {
        if((g_DCfan1Param.IOstate == 1) && (IO_DC_FAN_FEEDBACK1 == 0))
        {
            g_DCfan1Param.PulseCntCur ++;
        }
    }
    g_DCfan1Param.IOstate  = IO_DC_FAN_FEEDBACK1;
    
    if(g_DCfan2Param.AimSpeed > 0)
    {
        if((g_DCfan2Param.IOstate== 1) && (IO_DC_FAN_FEEDBACK2 == 0))
        {
            g_DCfan2Param.PulseCntCur ++;
        }
    }
    g_DCfan2Param.IOstate  = IO_DC_FAN_FEEDBACK2;
}


void Fan_FeedBack_Calc(void)
{
		DcFan_FeedBack();
		if(g_DCfan1Param.AimSpeed > 0)    
		{
				g_DCfan1Param.CtlTimeSpan ++;
		}
		if(g_DCfan2Param.AimSpeed > 0)    
		{
				g_DCfan2Param.CtlTimeSpan ++;
		}
}
/*******************************************************************************************
function name:  DcFan_init
description:    
*******************************************************************************************/
void DcFan_init()
{
    //timer2_io_config();
   // feedback_io_config();
    //init_timer2();
    memset(&g_DCfan1Param,0,sizeof(g_DCfan1Param));
    memset(&g_DCfan2Param,0,sizeof(g_DCfan2Param));
    g_DCfan1Param.duty = DCFAN_INITDUTY;
    g_DCfan2Param.duty = DCFAN_INITDUTY;     
}


#if 0
static void exter_interrupt_config(void)
{
    /* enable the GPIOA clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    /* enable the GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    
    /* configure external interrupt pin as input */
    gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
    gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
    
    /* enable the CFGCMP clock */
    rcu_periph_clock_enable(RCU_CFGCMP);
    /* enable and set key EXTI interrupt to the specified priority */
    
    nvic_irq_enable(EXTI0_1_IRQn, 0U);
    nvic_irq_enable(EXTI4_15_IRQn, 0U);

    /* connect feedBreak EXTI line to  GPIO pin */
    syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN7);
    syscfg_exti_line_config(EXTI_SOURCE_GPIOB, EXTI_SOURCE_PIN1);

    /* configure key EXTI line */
    exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
    exti_interrupt_flag_clear(EXTI_1);
    
    exti_init(EXTI_7, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
    exti_interrupt_flag_clear(EXTI_7);
}    


/*!
    \brief      this function handles external lines 0 to 1 interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI0_1_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_1)) {
        
        
        
        exti_interrupt_flag_clear(EXTI_1);
    }
}

/*!
    \brief      this function handles external lines 4 to 15 interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI4_15_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_7)) {
     
        
        exti_interrupt_flag_clear(EXTI_7);
    }
}
#endif
